﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Log.Repository;
using SPMS.Utility;

namespace SPMS.Log.Core
{
    /// <summary>
    /// 日志记录器适配器
    /// </summary>
    /// <remarks>提供了日志记录器的适配</remarks>
    /// <history>
    /// [zanezeng]               2009/10/14 11:58    创建
    /// </history>
    internal sealed class LoggerAdapter : ILogger
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="LoggerAdapter"/>的新实例
        /// </summary>
        /// <param name="name">要适配的日志记录器的名称</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><param name="repository"/>为<c>Null</c></exception>
        /// <history>
        /// [zanezeng]               2009/10/14 12:00    创建
        /// </history>
        public LoggerAdapter( ILoggingRepository repository, string name )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( repository, "repository" );

            //保存参数
            this.m_Repository = repository;
            this.m_Name = name;

            //挂接事件
            this.m_Repository.ConfigurationChanged += this.OnRepositoryChanged;
            this.m_Repository.ConfigurationReset += this.OnRepositoryChanged;
        }

        #endregion

        #region ---ILogger

        /// <summary>
        /// 获得日志记录器的名称
        /// </summary>
        /// <value></value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 11:54    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:04    创建
        /// </history>
        public string Name
        {
            get
            {
                return this.m_Name;
            }
        }

        /// <summary>
        /// 获得日志记录器所属的存储器
        /// </summary>
        /// <value>日志记录器所属的存储器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/13 15:19    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:01    创建
        /// </history>
        public ILoggingRepository Repository
        {
            get
            {
                return this.m_Repository;
            }
        }

        /// <summary>
        /// 获得或者设置当前日志记录器允许输出的最低日志级别
        /// </summary>
        /// <value>当前日志记录器允许输出的最低日志级别</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/8 11:31    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/8 11:35    创建
        /// </history>
        public Level Threshold
        {
            get
            {
                //判断适配的日志记录器是否存在
                if (null == this.AdaptedLogger)
                {
                    //记录日志
                    if (LoggingContext.MetaLog.IsErrorEnabled)
                    {
                        LoggingContext.MetaLog.Error( "无法从日志存储器'{0}'中获得日志记录器'{1}'", this.Repository, this.Name );
                    }

                    //直接返回关闭级别
                    return Level.Off;
                }

                //返回适配的日志记录器的级别
                return this.AdaptedLogger.Threshold;
            }
            set
            {
                //判断适配的日志记录器是否存在
                if (null == this.AdaptedLogger)
                {
                    //记录日志
                    if (LoggingContext.MetaLog.IsErrorEnabled)
                    {
                        LoggingContext.MetaLog.Error( "无法从日志存储器'{0}'中获得日志记录器'{1}'", this.Repository, this.Name );
                    }

                    //直接返回
                    return;
                }

                //设置适配的日志记录器的级别
                this.AdaptedLogger.Threshold = value;
            }
        }

        /// <summary>
        /// 判断当前日志记录器是否能够记录给定级别的日志信息
        /// </summary>
        /// <param name="level">用于判定的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：允许记录<br/>
        /// 	<c>false</c>：不允许记录
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 17:12    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:04    创建
        /// </history>
        public bool IsLevelEnabled( Level level )
        {
            //判断适配的日志记录器是否存在
            if (null == this.AdaptedLogger)
            {
                //记录日志
                if (LoggingContext.MetaLog.IsErrorEnabled)
                {
                    LoggingContext.MetaLog.Error( "无法从日志存储器'{0}'中获得日志记录器'{1}'", this.Repository, this.Name );
                }

                //直接返回不允许输出
                return false;
            }

            //转调
            return this.AdaptedLogger.IsLevelEnabled( level );
        }

        /// <summary>
        /// 将给定的日志信息记录到当前日志记录器中
        /// </summary>
        /// <param name="entry">要记录的日志条目</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 17:15    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:06    创建
        /// </history>
        public void WriteLog( LogEntry entry )
        {
            //判断需要记录的日志条目是否为NULL
            if (null == entry)
            {
                //输出日志
                if (LoggingContext.MetaLog.IsWarnEnabled)
                {
                    LoggingContext.MetaLog.Warn( "需要记录的日志条目为NULL" );
                }

                //如果需要记录的日志条目为NULL，则直接返回
                return;
            }

            //判断适配的日志记录器是否存在
            if (null == this.AdaptedLogger)
            {
                //记录日志
                if (LoggingContext.MetaLog.IsErrorEnabled)
                {
                    LoggingContext.MetaLog.Error( "无法从日志存储器'{0}'中获得日志记录器'{1}'，无法记录日志条目'{2}'", this.Repository, this.Name, entry );
                }

                //直接返回不允许输出
                return;
            }

            //转调
            this.AdaptedLogger.WriteLog( entry );
        }

        /// <summary>
        /// 将给定的日志信息记录到当前日志记录器中
        /// </summary>
        /// <param name="stackBoundaryType">调用堆栈分界类型</param>
        /// <param name="level">日志消息的级别</param>
        /// <param name="message">日志消息包含的消息对象</param>
        /// <param name="exception">日志消息包含的异常信息</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/13 15:08    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/14 12:07    创建
        /// </history>
        public void WriteLog( Type stackBoundaryType, Level level, object message, Exception exception )
        {
            //创建日志条目
            LogEntry entry = new LogEntry( stackBoundaryType, this.Name, level, message, exception );

            //转调
            this.WriteLog( entry );
        }

        /// <summary>
        /// 关闭当前日志记录器
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/19 9:50    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/19 9:52    创建
        /// </history>
        public void Close()
        {
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得适配的日志记录器
        /// </summary>
        /// <value>适配的日志记录器</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 19:00    创建
        /// </history>
        private ILogger AdaptedLogger
        {
            get
            {
                //判断适配的日志记录器是否已经创建
                if (null != this.m_AdaptedLogger)
                {
                    //如果已经创建，则直接返回
                    return this.m_AdaptedLogger;
                }

                //获得适配的日志记录器
                this.m_AdaptedLogger = this.Repository.GetLogger( this.Name );

                //返回适配的日志记录器
                return this.m_AdaptedLogger;
            }
        }

        #endregion

        #region ---Private Method

        /// <summary>
        /// 用于处理日志存储器变化事件
        /// </summary>
        /// <param name="sender">事件源</param>
        /// <param name="e">包含事件数据的<see cref="System.EventArgs"/>实例</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 10:48    创建
        /// </history>
        private void OnRepositoryChanged( object sender, EventArgs e )
        {
            //清除适配的日志记录器
            this.m_AdaptedLogger = null;
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 要适配的日志记录器的名称
        /// </summary>
        private string m_Name;

        /// <summary>
        /// 适配的日志记录器
        /// </summary>
        private volatile ILogger m_AdaptedLogger;

        /// <summary>
        /// 日志记录器所属的日志存储器
        /// </summary>
        private ILoggingRepository m_Repository;

        #endregion
    }
}
